package com.bm.server.serverImpl;

import com.bm.dao.*;
import com.bm.pojo.addr.PlaceOrigin;
import com.bm.pojo.disease.Disease;
import com.bm.pojo.relationship.NodeRelationship;
import com.bm.pojo.sort.AllNode;
import com.bm.pojo.sort.GrapeSort;
import com.bm.pojo.wine.Wine;
import com.bm.server.Neo4jViewActionServer;
import com.google.gson.Gson;
import org.neo4j.driver.Record;
import org.neo4j.driver.StatementResult;
import org.neo4j.driver.Value;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Relationship;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: sx
 * Date: 2022/2/9
 * Time: 20:17
 * Description: java
 */
@Service
public class Neo4jViewActionServerImpl implements Neo4jViewActionServer {
    @Resource
    private Neo4jGrapeRepository neo4jGrapeRepository;
    @Autowired
    private Neo4jIndexDao neo4jIndexDao;
    @Resource
    private Neo4jPlaceOriginRepository neo4jPlaceOriginRepository;
    @Resource
    private Neo4jDiseaseRepository neo4jDiseaseRepository;
    @Resource
    private Neo4jWineRepository neo4jWineRepository;

    @Override
    public String getSearchString(String string) {
        String msgString="";
        String cql = "match (n:grapeTu)-[r:`产区`]->(p:producingArea) where n.grapeName=~"+"'.*" + string + ".*'"+"or p.name=~"+"'.*" + string + ".*'"+" return n,r,p";
        HashMap list = neo4jIndexDao.getList(cql);
        if(list.size()<1 || list==null){
            msgString= "查无此节点";
        }else {
            Gson gson = new Gson();
            msgString = gson.toJson(list);
        }
        return msgString;
    }

    @Override
    public List<String> getSort() {
        List<String> list = new ArrayList<>();
        Iterable<GrapeSort> all = neo4jGrapeRepository.findAll();
        for (GrapeSort g:all
             ) {

            list.add(g.getGrapeName());
            
        }
        return list;
    }

    @Override
    public List<String> getPlaceOrigin() {
        List<String> list = new ArrayList<>();
        Iterable<PlaceOrigin> all = neo4jPlaceOriginRepository.findAll();
        for (PlaceOrigin p:all
        ) {

            list.add(p.getName());

        }
        return list;

    }

    @Override
    public List<String> wine() {
        List<String> list = new ArrayList<>();
        Iterable<Wine> all = neo4jWineRepository.findAll();
        for (Wine p:all
        ) {

            list.add(p.getName());

        }
        return list;
    }

    @Override
    public List<String> disease() {
        List<String> list = new ArrayList<>();
        Iterable<Disease> all = neo4jDiseaseRepository.findAll();
        for (Disease p:all
        ) {

            list.add(p.getName());

        }
        return list;
    }

    @Override
    public String getsSearching(String string,Integer jingDu) {
        double flag=0.0;
        //精准度
        if(jingDu==1){
            flag=0.5;
        }else if(jingDu==2){
            flag=0.3;
        }else {
            flag=0.05;
        }
        List<Record> list=null;
        StatementResult indexNode = neo4jIndexDao.getIndexNode(string,flag);
        list=indexNode.list();

        List<Map<String,String>> nodeNames = new ArrayList<>();
        String json="";
        if(list.size()>0 && list !=null){
            for (Record record:list) {
                Value value = record.get(0);
                Node node = value.asNode();
                Map<String, Object> getNode = node.asMap();
                Map<String, String> Map = new HashMap<>();

                if(getNode.get("grapeName")!=null){
                    Map.put("name",(String) getNode.get("grapeName"));
                    Map.put("label",(String) getNode.get("label"));
                    Map.put("details",(String) getNode.get("details"));

                }else {
                    Map.put("name",(String) getNode.get("name"));
                    Map.put("label",(String) getNode.get("label"));
                    Map.put("details",(String) getNode.get("details"));
                }
                nodeNames.add(Map);
            }
        }else {
            return null;
        }

        // 去重
        HashSet<AllNode> allNodes = new HashSet<>();
        List<AllNode> nodes = new ArrayList<>();
        List<NodeRelationship> links = new ArrayList<>();

            for (int i=0;i<nodeNames.size();i++){
                // 获取检索节点的子节点
                List<Record> nodeToRetrieve = neo4jIndexDao.getNodeToRetrieve(nodeNames.get(i));

                for (Record r:nodeToRetrieve) {
                    if(r.size()>1){
                        Node node1 = r.get(0).asNode();
                        AllNode start = getNode(node1);
                        Relationship relationship = r.get(1).asRelationship();
                        NodeRelationship relationship1 = getRelationship(relationship);
                        Node node2 = r.get(2).asNode();
                        AllNode end = getNode(node2);
                        nodes.add(start);
                        nodes.add(end);
                        allNodes.add(start);
                        allNodes.add(end);
                        links.add(relationship1);
                    }else {
                        Node node1 = r.get(0).asNode();
                        AllNode start = getNode(node1);
                        nodes.add(start);
                    }
                }

            }


        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("nodes",allNodes);
        hashMap.put("links",links);
        //获取相似度前十的节点

            if(nodeNames.size()>=10){
                List<Map<String, String>> maps = nodeNames.subList(0, 10);
                hashMap.put("list",maps);
            }else{
                hashMap.put("list",nodeNames);
            }

        Gson gson = new Gson();
        json = gson.toJson(hashMap);//转成字符串

        return json;
    }

    @Override
    public String getAllNodes() {

        HashMap<String, List<Record>> nodeToRetrieve = neo4jIndexDao.getAll();
        HashSet<AllNode> allNodes = new HashSet<>();
        List<NodeRelationship> links = new ArrayList<>();
        for (Record r:nodeToRetrieve.get("nodes")) {

                Node node1 = r.get(0).asNode();
                AllNode node = getNode(node1);
                if(node.getLabel() ==null && node.getDetails()==null){
                    continue;
                }
                allNodes.add(node);

        }
        for (Record r:nodeToRetrieve.get("links")) {

                Relationship relationship = r.get(0).asRelationship();
                NodeRelationship relationship1 = getRelationship(relationship);
                links.add(relationship1);

        }

        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("nodes",allNodes);
        hashMap.put("links",links);
        hashMap.put("list","");
        Gson gson = new Gson();
        return gson.toJson(hashMap);//转成字符串
    }


    /**
     * 重新整理节点
     * @param node
     * @return
     */
    public AllNode getNode(Node node){

        Map<String, Object> nodeMap = node.asMap();
        AllNode start = new AllNode();
        if(nodeMap.get("grapeName")!=null){
            start.setName((String)nodeMap.get("grapeName"));
        }else {
            start.setName((String)nodeMap.get("name"));
        }
        start.setDetails((String)nodeMap.get("details"));
        start.setId(node.id());
        start.setLabel((String)nodeMap.get("label"));

        return start;
    }


    /**
     *
     * @param relationship
     * @return
     */
    public NodeRelationship getRelationship(Relationship relationship){
        NodeRelationship nodeRelationship = new NodeRelationship();
        nodeRelationship.setSource(relationship.startNodeId());
        nodeRelationship.setTarget(relationship.endNodeId());
        nodeRelationship.setType(relationship.type());
        return nodeRelationship;
    }
}
